#include "num2048.h"

// 方块颜色定义（2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096+）
const uint16_t Num2048::TILE_COLORS[12] = {
  0xEEE4,  // 2 - 浅灰
  0xEDC0,  // 4 - 米黄
  0xFB60,  // 8 - 橙色
  0xFB00,  // 16 - 深橙
  0xFB00,  // 32 - 橙红
  0xFA00,  // 64 - 红色
  0xFDE0,  // 128 - 淡黄
  0xFDC0,  // 256 - 金黄
  0xFDA0,  // 512 - 深金
  0xFC80,  // 1024 - 金橙
  0xFC20,  // 2048 - 金色
  0x3186   // 4096+ - 深色
};

// 文字颜色定义
const uint16_t Num2048::TEXT_COLORS[12] = {
  0x7BCF,     // 2 - 深灰文字
  0x7BCF,     // 4 - 深灰文字
  TFT_WHITE,  // 8+ - 白色文字
  TFT_WHITE,
  TFT_WHITE,
  TFT_WHITE,
  TFT_WHITE,
  TFT_WHITE,
  TFT_WHITE,
  TFT_WHITE,
  TFT_WHITE,
  TFT_WHITE
};

// ========== 初始化与绘制函数 ==========

// 初始化游戏
void Num2048::initGame() {
  // 清空网格
  for (int i = 0; i < GRID_SIZE; i++) {
    for (int j = 0; j < GRID_SIZE; j++) {
      grid[i][j] = 0;
    }
  }

  // 初始化游戏数据
  score = 0;
  bestScore = 0;  // 可以从EEPROM读取保存的最高分
  state = PLAYING;
  moved = false;
  hasWon = false;

  lastMoveTime = millis();

  // 随机种子
  randomSeed(millis());

  // 添加初始的两个数字
  addRandomTile();
  addRandomTile();
}

// 绘制游戏区域边框
void Num2048::drawGameArea(Screen &screen) {
  // 绘制游戏背景
  int gridWidth = GRID_SIZE * CELL_SIZE + (GRID_SIZE + 1) * CELL_PADDING;
  int gridHeight = GRID_SIZE * CELL_SIZE + (GRID_SIZE + 1) * CELL_PADDING;

  screen.spr.fillRoundRect(
    GRID_OFFSET_X - 2,
    GRID_OFFSET_Y - 2,
    gridWidth + 4,
    gridHeight + 4,
    4,
    0xBDF7  // 灰色背景
  );
}

// 绘制网格
void Num2048::drawGrid(Screen &screen) {
  for (int row = 0; row < GRID_SIZE; row++) {
    for (int col = 0; col < GRID_SIZE; col++) {
      drawCell(screen, row, col, grid[row][col]);
    }
  }
}

// 绘制单个格子
void Num2048::drawCell(Screen &screen, int row, int col, int value) {
  int x = GRID_OFFSET_X + col * (CELL_SIZE + CELL_PADDING) + CELL_PADDING;
  int y = GRID_OFFSET_Y + row * (CELL_SIZE + CELL_PADDING) + CELL_PADDING;

  uint16_t bgColor;

  if (value == 0) {
    // 空格子
    bgColor = 0xCE79;  // 浅灰色
    screen.spr.fillRoundRect(x, y, CELL_SIZE, CELL_SIZE, 3, bgColor);
  } else {
    // 有数字的格子
    bgColor = getTileColor(value);
    uint16_t textColor = getTextColor(value);

    screen.spr.fillRoundRect(x, y, CELL_SIZE, CELL_SIZE, 3, bgColor);

    // 绘制数字
    screen.spr.setTextColor(textColor, bgColor);
    screen.spr.setTextDatum(CC_DATUM);

    String valueStr = getValueString(value);

    // 根据数字大小调整字体
    if (value >= 1024) {
      screen.spr.drawString(valueStr, x + CELL_SIZE / 2, y + CELL_SIZE / 2, 2);
    } else if (value >= 128) {
      screen.spr.drawString(valueStr, x + CELL_SIZE / 2, y + CELL_SIZE / 2, 4);
    } else {
      screen.spr.drawString(valueStr, x + CELL_SIZE / 2, y + CELL_SIZE / 2, 4);
    }
  }
}

// 绘制游戏信息
void Num2048::drawInfo(Screen &screen) {
  screen.spr.setTextColor(TFT_WHITE, TFT_BLACK);
  screen.spr.setTextDatum(TL_DATUM);

  // 分数
  screen.spr.drawString("分数:", SCORE_TITLE_X, SCORE_TITLE_Y, 2);
  screen.spr.fillRect(SCORE_VALUE_X, SCORE_VALUE_Y, 60, 16, TFT_BLACK);
  screen.spr.drawNumber(score, SCORE_VALUE_X, SCORE_VALUE_Y, 2);

  // 最高分
  screen.spr.drawString("最高分:", BEST_TITLE_X, BEST_TITLE_Y, 2);
  screen.spr.fillRect(BEST_VALUE_X, BEST_VALUE_Y, 60, 16, TFT_BLACK);
  screen.spr.drawNumber(bestScore, BEST_VALUE_X, BEST_VALUE_Y, 2);

  // 操作说明
  screen.spr.setTextColor(TFT_CYAN, TFT_BLACK);
  screen.spr.drawString("操作:", CONTROL_TITLE_X, CONTROL_TITLE_Y, 1);
  screen.spr.setTextColor(TFT_WHITE, TFT_BLACK);
  screen.spr.drawString("方向键: 移动", CONTROL_VALUE_X, CONTROL_VALUE_Y, 1);
  screen.spr.drawString("A: 暂停", CONTROL_VALUE_X, CONTROL_TITLE_Y + 20, 1);
  screen.spr.drawString("X: 退出", CONTROL_VALUE_X, CONTROL_TITLE_Y + 40, 1);
}

// 绘制暂停提示
void Num2048::drawPausedMessage(Screen &screen) {
  screen.spr.fillRect(40, 220, 160, 80, TFT_DARKGREY);
  screen.spr.drawRect(40, 220, 160, 80, TFT_WHITE);
  screen.spr.setTextColor(TFT_YELLOW, TFT_DARKGREY);
  screen.spr.setTextDatum(CC_DATUM);
  screen.spr.drawString("暂停", TFT_WIDTH / 2, 250, 4);
  screen.spr.setTextColor(TFT_WHITE, TFT_DARKGREY);
  screen.spr.drawString("按 A 键继续", TFT_WIDTH / 2, 280, 2);
  screen.spr.setTextDatum(TL_DATUM);
}

// 绘制游戏结束界面
void Num2048::drawGameOver(Screen &screen) {
  screen.spr.fillRect(30, 200, 180, 120, TFT_RED);
  screen.spr.drawRect(30, 200, 180, 120, TFT_WHITE);
  screen.spr.setTextColor(TFT_WHITE, TFT_RED);
  screen.spr.setTextDatum(CC_DATUM);
  screen.spr.drawString("游戏结束", TFT_WIDTH / 2, 230, 4);
  screen.spr.drawString("分数: " + String(score), TFT_WIDTH / 2, 260, 2);
  screen.spr.drawString("最高分: " + String(bestScore), TFT_WIDTH / 2, 280, 2);
  screen.spr.drawString("B: 重来 X: 退出", TFT_WIDTH / 2, 300, 2);
  screen.spr.setTextDatum(TL_DATUM);
}

// 绘制胜利界面
void Num2048::drawWin(Screen &screen) {
  screen.spr.fillRect(30, 200, 180, 120, TFT_DARKGREEN);
  screen.spr.drawRect(30, 200, 180, 120, TFT_WHITE);
  screen.spr.setTextColor(TFT_YELLOW, TFT_DARKGREEN);
  screen.spr.setTextDatum(CC_DATUM);
  screen.spr.drawString("你赢了", TFT_WIDTH / 2, 230, 4);
  screen.spr.setTextColor(TFT_WHITE, TFT_DARKGREEN);
  screen.spr.drawString("达到了 2048", TFT_WIDTH / 2, 260, 2);
  screen.spr.drawString("O: 继续", TFT_WIDTH / 2, 280, 2);
  screen.spr.drawString("B: 重来  X: 退出", TFT_WIDTH / 2, 300, 2);
  screen.spr.setTextDatum(TL_DATUM);
}

// ========== 游戏逻辑函数 ==========

// 添加随机数字方块（2或4）
void Num2048::addRandomTile() {
  // 收集所有空格子
  int emptyCount = 0;
  int emptyPos[GRID_SIZE * GRID_SIZE][2];

  for (int i = 0; i < GRID_SIZE; i++) {
    for (int j = 0; j < GRID_SIZE; j++) {
      if (grid[i][j] == 0) {
        emptyPos[emptyCount][0] = i;
        emptyPos[emptyCount][1] = j;
        emptyCount++;
      }
    }
  }

  if (emptyCount > 0) {
    // 随机选择一个空格子
    int idx = random(emptyCount);
    int row = emptyPos[idx][0];
    int col = emptyPos[idx][1];

    // 90%概率生成2，10%概率生成4
    grid[row][col] = (random(10) < 9) ? 2 : 4;
  }
}

// 合并一行（向左合并）
void Num2048::mergeLine(int line[GRID_SIZE], int &lineScore) {
  // 先移除所有0，向左压缩
  int temp[GRID_SIZE] = { 0 };
  int pos = 0;

  for (int i = 0; i < GRID_SIZE; i++) {
    if (line[i] != 0) {
      temp[pos++] = line[i];
    }
  }

  // 合并相同的数字
  for (int i = 0; i < GRID_SIZE - 1; i++) {
    if (temp[i] != 0 && temp[i] == temp[i + 1]) {
      temp[i] *= 2;
      lineScore += temp[i];
      temp[i + 1] = 0;
    }
  }

  // 再次压缩
  pos = 0;
  for (int i = 0; i < GRID_SIZE; i++) {
    if (temp[i] != 0) {
      line[pos++] = temp[i];
    }
  }

  // 填充剩余位置为0
  while (pos < GRID_SIZE) {
    line[pos++] = 0;
  }
}

// 顺时针旋转90度
void Num2048::rotateCW() {
  int temp[GRID_SIZE][GRID_SIZE];

  for (int i = 0; i < GRID_SIZE; i++) {
    for (int j = 0; j < GRID_SIZE; j++) {
      temp[j][GRID_SIZE - 1 - i] = grid[i][j];
    }
  }

  for (int i = 0; i < GRID_SIZE; i++) {
    for (int j = 0; j < GRID_SIZE; j++) {
      grid[i][j] = temp[i][j];
    }
  }
}

// 逆时针旋转90度
void Num2048::rotateCCW() {
  int temp[GRID_SIZE][GRID_SIZE];

  for (int i = 0; i < GRID_SIZE; i++) {
    for (int j = 0; j < GRID_SIZE; j++) {
      temp[GRID_SIZE - 1 - j][i] = grid[i][j];
    }
  }

  for (int i = 0; i < GRID_SIZE; i++) {
    for (int j = 0; j < GRID_SIZE; j++) {
      grid[i][j] = temp[i][j];
    }
  }
}

// 移动
bool Num2048::move(int direction) {
  // 保存原始状态用于比较
  int oldGrid[GRID_SIZE][GRID_SIZE];
  for (int i = 0; i < GRID_SIZE; i++) {
    for (int j = 0; j < GRID_SIZE; j++) {
      oldGrid[i][j] = grid[i][j];
    }
  }

  int moveScore = 0;

  // 根据方向旋转网格，统一按左移处理
  // 0=上, 1=右, 2=下, 3=左
  switch (direction) {
    case 0:  // 上 -> 逆时针90度，左移，顺时针90度
      rotateCCW();
      break;
    case 1:  // 右 -> 旋转180度，左移，旋转180度
      rotateCW();
      rotateCW();
      break;
    case 2:  // 下 -> 顺时针90度，左移，逆时针90度
      rotateCW();
      break;
    case 3:  // 左 -> 不旋转
      break;
  }

  // 对每一行进行合并
  for (int i = 0; i < GRID_SIZE; i++) {
    mergeLine(grid[i], moveScore);
  }

  // 旋转回来
  switch (direction) {
    case 0:  // 上
      rotateCW();
      break;
    case 1:  // 右
      rotateCW();
      rotateCW();
      break;
    case 2:  // 下
      rotateCCW();
      break;
    case 3:  // 左
      break;
  }

  // 检查是否真的移动了
  bool hasMoved = false;
  for (int i = 0; i < GRID_SIZE; i++) {
    for (int j = 0; j < GRID_SIZE; j++) {
      if (grid[i][j] != oldGrid[i][j]) {
        hasMoved = true;
        break;
      }
    }
    if (hasMoved)
      break;
  }

  if (hasMoved) {
    score += moveScore;
    if (score > bestScore) {
      bestScore = score;
    }

    // 检查是否达到2048
    if (!hasWon) {
      for (int i = 0; i < GRID_SIZE; i++) {
        for (int j = 0; j < GRID_SIZE; j++) {
          if (grid[i][j] == 2048) {
            hasWon = true;
            state = WIN;
            return true;
          }
        }
      }
    }
  }

  return hasMoved;
}

// 检查是否有空格子
bool Num2048::hasEmptyCell() {
  for (int i = 0; i < GRID_SIZE; i++) {
    for (int j = 0; j < GRID_SIZE; j++) {
      if (grid[i][j] == 0) {
        return true;
      }
    }
  }
  return false;
}

// 检查是否还能移动
bool Num2048::canMove() {
  // 有空格子就能移动
  if (hasEmptyCell()) {
    return true;
  }

  // 检查是否有相邻的相同数字
  for (int i = 0; i < GRID_SIZE; i++) {
    for (int j = 0; j < GRID_SIZE; j++) {
      int current = grid[i][j];

      // 检查右边
      if (j < GRID_SIZE - 1 && grid[i][j + 1] == current) {
        return true;
      }

      // 检查下边
      if (i < GRID_SIZE - 1 && grid[i + 1][j] == current) {
        return true;
      }
    }
  }

  return false;
}

// ========== 输入处理 ==========

void Num2048::handleInput(Keys &keys) {
  keys.kvs_update();

  unsigned long currentTime = millis();

  // 暂停/继续
  if (keys.a.pressed()) {
    if (state == PLAYING) {
      state = PAUSED;
    } else if (state == PAUSED) {
      state = PLAYING;
    }
    delay(200);  // 防抖
  }

  // 游戏进行中的控制
  if (state == PLAYING) {
    // 防止移动过快
    if (currentTime - lastMoveTime < 150) {
      return;
    }

    bool hasMoved = false;

    // 方向键控制移动
    if (keys.up.pressed()) {
      hasMoved = move(0);  // 上
      lastMoveTime = currentTime;
    } else if (keys.right.pressed()) {
      hasMoved = move(1);  // 右
      lastMoveTime = currentTime;
    } else if (keys.down.pressed()) {
      hasMoved = move(2);  // 下
      lastMoveTime = currentTime;
    } else if (keys.left.pressed()) {
      hasMoved = move(3);  // 左
      lastMoveTime = currentTime;
    }

    // 如果移动成功，添加新数字
    if (hasMoved) {
      if (state != WIN) {  // 获胜状态不添加新数字
        addRandomTile();

        // 检查游戏是否结束
        if (!canMove()) {
          state = GAME_OVER;
        }
      }
    }
  } else if (state == WIN) {
    // 获胜后可以选择继续
    if (keys.o.pressed()) {
      state = PLAYING;
      delay(200);
    }
  }
}

// ========== 工具函数 ==========

// 计算log2值
int Num2048::log2(int n) {
  int result = 0;
  while (n > 1) {
    n /= 2;
    result++;
  }
  return result;
}

// 获取方块颜色
uint16_t Num2048::getTileColor(int value) {
  if (value == 0)
    return 0xCE79;

  int index = log2(value) - 1;  // 2->0, 4->1, 8->2, ...
  if (index < 0)
    index = 0;
  if (index >= 12)
    index = 11;

  return TILE_COLORS[index];
}

// 获取文字颜色
uint16_t Num2048::getTextColor(int value) {
  if (value == 0)
    return TFT_BLACK;

  int index = log2(value) - 1;
  if (index < 0)
    index = 0;
  if (index >= 12)
    index = 11;

  return TEXT_COLORS[index];
}

// 获取数字显示文本
String Num2048::getValueString(int value) {
  if (value == 0)
    return "";
  return String(value);
}

// ========== 主游戏循环 ==========

void Num2048::main(Screen &screen, Keys &keys) {
  // 初始化游戏
  initGame();

  // 清屏并设置文本对齐方式
  screen.clearAndLeft();

  // 绘制初始界面
  drawGameArea(screen);
  drawGrid(screen);
  drawInfo(screen);
  screen.drawScreen();

  // 游戏主循环
  while (true) {
    // 处理输入
    handleInput(keys);

    // 检查是否退出
    if (keys.x.pressed()) {
      screen.clearAndCenter();
      return;
    }

    // 根据游戏状态绘制
    if (state == PLAYING) {
      // 重绘游戏画面
      screen.spr.fillRect(0, GRID_OFFSET_Y - 5, TFT_WIDTH, TFT_HEIGHT - GRID_OFFSET_Y + 5, TFT_BLACK);
      drawGameArea(screen);
      drawGrid(screen);
      drawInfo(screen);
    } else if (state == PAUSED) {
      // 暂停状态
      drawPausedMessage(screen);
    } else if (state == WIN) {
      // 胜利状态
      drawWin(screen);
      screen.drawScreen();

      // 等待玩家选择
      while (state == WIN) {
        keys.kvs_update();

        if (keys.o.pressed()) {
          // 继续游戏
          state = PLAYING;
          delay(200);
          break;
        }

        if (keys.b.pressed()) {
          // 重新开始
          main(screen, keys);
          return;
        }

        if (keys.x.pressed()) {
          // 退出
          screen.clearAndCenter();
          return;
        }

        delay(10);
      }
    } else if (state == GAME_OVER) {
      // 游戏结束
      drawGameOver(screen);
      screen.drawScreen();

      // 等待玩家选择
      while (true) {
        keys.kvs_update();

        if (keys.b.pressed()) {
          // 重新开始
          main(screen, keys);
          return;
        }

        if (keys.x.pressed()) {
          // 退出
          screen.clearAndCenter();
          return;
        }

        delay(10);
      }
    }

    // 更新屏幕
    screen.drawScreen();

    delay(10);  // 降低CPU使用率
  }
}
